<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>学生成绩管理系统</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
        }

        :root {
            --primary: #4F46E5;
            --primary-dark: #4338CA;
            --secondary: #10B981;
            --tertiary: #F59E0B;
            --light: #F9FAFB;
            --dark: #1F2937;
            --gray: #6B7280;
            --light-gray: #E5E7EB;
            --border: #D1D5DB;
            --card-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
            --success: #10B981;
            --warning: #F59E0B;
            --rank1: #FFD700;
            --rank2: #C0C0C0;
            --rank3: #CD7F32;
            --danger: #EF4444;
            --update: #3B82F6;
        }

        body {
            background: linear-gradient(135deg, #f0f7ff 0%, #f8fafc 100%);
            color: var(--dark);
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
        }

        header {
            background: white;
            border-radius: 16px;
            box-shadow: var(--card-shadow);
            padding: 20px 30px;
            margin-bottom: 30px;
            display: flex;
            flex-direction: column;
            gap: 20px;
        }

        .header-top {
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 20px;
        }

        .logo {
            display: flex;
            align-items: center;
            gap: 12px;
            font-size: 1.5rem;
            font-weight: 700;
            color: var(--primary);
        }

        .logo i {
            font-size: 1.8rem;
        }

        .exam-selector {
            display: flex;
            gap: 15px;
            flex-wrap: wrap;
            margin-top: 10px;
        }

        .exam-btn {
            padding: 8px 16px;
            border-radius: 8px;
            background: #E0E7FF;
            color: var(--primary);
            font-weight: 600;
            border: none;
            cursor: pointer;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 8px;
            position: relative;
        }

        .exam-btn:hover {
            background: var(--primary);
            color: white;
        }

        .exam-btn.active {
            background: var(--primary);
            color: white;
            box-shadow: 0 4px 6px rgba(79, 70, 229, 0.3);
        }

        .exam-btn.add {
            background: var(--secondary);
            color: white;
        }

        .exam-btn.add:hover {
            background: #0d9e6d;
        }

        .delete-exam-btn {
            position: absolute;
            top: -8px;
            right: -8px;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            background: var(--danger);
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            cursor: pointer;
            opacity: 0;
            transition: opacity 0.3s ease, transform 0.3s ease;
            transform: scale(0.8);
            border: 2px solid white;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            z-index: 10;
        }

        .exam-btn:hover .delete-exam-btn {
            opacity: 1;
            transform: scale(1);
        }

        .delete-exam-btn:hover {
            background: #DC2626;
            transform: scale(1.1) !important;
        }

        .header-controls {
            display: flex;
            gap: 15px;
            flex-wrap: wrap;
            margin-top: 10px;
            position: relative;
        }

        .class-filter {
            display: flex;
            align-items: center;
            gap: 10px;
        }

        select {
            padding: 10px 15px;
            border-radius: 8px;
            border: 1px solid var(--border);
            background: white;
            font-size: 1rem;
            min-width: 150px;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        select:focus {
            outline: none;
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
        }

        .file-upload {
            position: relative;
            display: inline-block;
        }

        .file-upload-btn {
            display: inline-flex;
            align-items: center;
            gap: 8px;
            background: var(--primary);
            color: white;
            padding: 10px 20px;
            border-radius: 8px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            border: none;
        }

        .file-upload-btn:hover {
            background: var(--primary-dark);
            transform: translateY(-2px);
        }

        .file-upload-btn.update {
            background: #60A5FA;
        }

        .file-upload-btn.reset {
            background: #DC2626;
        }

        .file-upload-btn.export {
            background: #16A34A;
            position: relative;
        }

        .file-upload-btn.update-data {
            background: var(--update);
        }

        #file-input {
            position: absolute;
            left: 0;
            top: 0;
            opacity: 0;
            width: 100%;
            height: 100%;
            cursor: pointer;
        }

        .stats {
            display: flex;
            gap: 15px;
            margin-top: 10px;
            flex-wrap: wrap;
        }

        .stat-card {
            background: var(--light);
            border-radius: 10px;
            padding: 12px 20px;
            display: flex;
            align-items: center;
            gap: 10px;
            min-width: 180px;
        }

        .stat-icon {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2rem;
        }

        .stat-content {
            display: flex;
            flex-direction: column;
        }

        .stat-value {
            font-size: 1.4rem;
            font-weight: 700;
        }

        .stat-label {
            font-size: 0.9rem;
            color: var(--gray);
        }

        .table-container {
            background: white;
            border-radius: 16px;
            box-shadow: var(--card-shadow);
            padding: 25px;
            overflow-x: auto;
        }

        .table-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            flex-wrap: wrap;
            gap: 15px;
        }

        .table-title {
            font-size: 1.5rem;
            font-weight: 600;
            color: var(--dark);
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .search-box {
            display: flex;
            align-items: center;
            background: var(--light);
            border-radius: 8px;
            padding: 8px 15px;
            border: 1px solid var(--border);
        }

        .search-box input {
            border: none;
            background: transparent;
            padding: 5px 10px;
            font-size: 1rem;
            min-width: 215px;
        }

        .search-box input:focus {
            outline: none;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }

        thead {
            background: var(--light);
        }

        th {
            padding: 15px;
            text-align: left;
            font-weight: 600;
            color: var(--dark);
            border-bottom: 2px solid var(--border);
            position: relative;
        }

        th:hover {
            background: #f3f4f6;
        }

        .sort-icon {
            position: absolute;
            right: 10px;
            color: var(--gray);
            font-size: 0.8rem;
        }

        td {
            padding: 15px;
            border-bottom: 1px solid var(--border);
        }

        tr:last-child td {
            border-bottom: none;
        }

        tr:hover {
            background: rgba(79, 70, 229, 0.05);
        }

        .student-id {
            font-weight: 600;
            color: var(--primary);
        }

        .class-badge {
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 0.85rem;
            font-weight: 500;
            background: #DBEAFE;
            color: #1D4ED8;
        }

        .actions {
            display: flex;
            gap: 10px;
        }

        .action-btn {
            width: 36px;
            height: 36px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            background: var(--light);
            color: var(--gray);
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .action-btn:hover {
            background: var(--primary);
            color: white;
            transform: scale(1.1);
        }

        .score-high {
            color: var(--success);
            font-weight: 600;
        }

        .score-medium {
            color: var(--warning);
        }

        .score-low {
            color: #EF4444;
        }

        .rank-1 {
            background: linear-gradient(135deg, #FFD700 0%, #FFEC8B 100%);
            font-weight: bold;
            color: #8B7500;
        }

        .rank-2 {
            background: linear-gradient(135deg, #C0C0C0 0%, #E0E0E0 100%);
            font-weight: bold;
            color: #696969;
        }

        .rank-3 {
            background: linear-gradient(135deg, #CD7F32 0%, #E6B17E 100%);
            font-weight: bold;
            color: #5E3A1D;
        }

        .rank-cell {
            display: inline-block;
            width: 30px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            border-radius: 50%;
            font-weight: bold;
        }

        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: var(--gray);
        }

        .empty-state i {
            font-size: 4rem;
            color: var(--light-gray);
            margin-bottom: 20px;
        }

        .empty-state p {
            font-size: 1.2rem;
            max-width: 500px;
            margin: 0 auto;
        }

        .file-requirements {
            background: #F3F4F6;
            border-radius: 8px;
            padding: 15px;
            margin-top: 20px;
            font-size: 0.9rem;
        }

        .file-requirements h4 {
            margin-bottom: 10px;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 1000;
            justify-content: center;
            align-items: center;
        }

        .modal-content {
            background: white;
            border-radius: 16px;
            padding: 30px;
            width: 90%;
            max-width: 500px;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
        }

        .modal-title {
            font-size: 1.5rem;
            font-weight: 600;
        }

        .close-modal {
            background: none;
            border: none;
            font-size: 1.5rem;
            cursor: pointer;
            color: var(--gray);
        }

        .form-group {
            margin-bottom: 20px;
        }

        .form-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
        }

        .form-group input {
            width: 100%;
            padding: 12px 15px;
            border-radius: 8px;
            border: 1px solid var(--border);
            font-size: 1rem;
        }

        .form-group input:focus {
            outline: none;
            border-color: var(--primary);
        }

        .modal-actions {
            display: flex;
            gap: 15px;
            justify-content: flex-end;
            margin-top: 20px;
        }

        .modal-btn {
            padding: 10px 20px;
            border-radius: 8px;
            font-weight: 600;
            cursor: pointer;
            border: none;
            transition: all 0.3s ease;
        }

        .modal-btn.primary {
            background: var(--primary);
            color: white;
        }

        .modal-btn.primary:hover {
            background: var(--primary-dark);
        }

        .modal-btn.secondary {
            background: #E5E7EB;
            color: var(--dark);
        }

        .modal-btn.secondary:hover {
            background: #D1D5DB;
        }

        .modal-btn.danger {
            background: var(--danger);
            color: white;
        }

        .modal-btn.danger:hover {
            background: #DC2626;
        }

        footer {
            text-align: center;
            padding: 30px 0;
            color: var(--gray);
            margin-top: 40px;
        }

        .export-options {
            display: none;
            position: absolute;
            background: white;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            padding: 15px;
            z-index: 100;
            margin-top: 5px;
            min-width: 200px;
            right: 0;
            top: 100%;
        }

        .export-options.active {
            display: block;
        }

        .export-option {
            padding: 8px 12px;
            border-radius: 6px;
            cursor: pointer;
            margin-bottom: 5px;
            transition: all 0.3s;
        }

        .export-option:hover {
            background: #EFF6FF;
        }

        .export-option i {
            margin-right: 8px;
        }

        #loading-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(255, 255, 255, 0.9);
            display: none;
            justify-content: center;
            align-items: center;
            z-index: 2000;
            transition: opacity 0.5s ease;
        }

        .loader {
            text-align: center;
        }

        .loader-spinner {
            width: 50px;
            height: 50px;
            border: 5px solid rgba(79, 70, 229, 0.2);
            border-radius: 50%;
            border-top-color: var(--primary);
            animation: spin 1s linear infinite;
            margin: 0 auto 20px;
        }

        @keyframes spin {
            to {
                transform: rotate(360deg);
            }
        }

        .status-indicator {
            position: absolute;
            top: -5px;
            right: -5px;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background: #10B981;
            border: 2px solid white;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
        }

        .status-indicator.outdated {
            background: #EF4444;
        }

        .status-indicator.loading {
            background: #F59E0B;
            animation: pulse 1.5s infinite;
        }

        @keyframes pulse {
            0% {
                transform: scale(1);
                opacity: 1;
            }

            50% {
                transform: scale(1.2);
                opacity: 0.7;
            }

            100% {
                transform: scale(1);
                opacity: 1;
            }
        }

        @media (max-width: 768px) {
            .header-top {
                flex-direction: column;
                align-items: flex-start;
            }

            .header-controls {
                width: 100%;
            }

            .class-filter,
            .file-upload {
                width: 100%;
            }

            select {
                width: 100%;
            }

            .file-upload-btn {
                width: 100%;
                justify-content: center;
            }

            .stats {
                width: 100%;
            }

            .stat-card {
                flex: 1;
                min-width: 0;
            }

            th,
            td {
                padding: 10px;
                font-size: 0.9rem;
            }
        }

        @media (max-width: 480px) {
            .table-header {
                flex-direction: column;
                align-items: flex-start;
            }

            .search-box {
                width: 100%;
            }

            .search-box input {
                width: 100%;
            }

            .logo span {
                font-size: 1.2rem;
            }

            .exam-btn span {
                display: none;
            }

            .table-container {
                padding: 15px;
            }

            .delete-exam-btn {
                top: -5px;
                right: -5px;
                width: 20px;
                height: 20px;
                font-size: 10px;
            }
        }
    </style>
</head>

<body>
    <div id="loading-overlay">
        <div class="loader">
            <div class="loader-spinner"></div>
            <p>正在加载考试数据...</p>
        </div>
    </div>

    <div class="container">
        <header>
            <div class="header-top">
                <div class="logo">
                    <i class="fas fa-user-graduate"></i>
                    <span>学生成绩管理系统</span>
                </div>

                <div class="header-controls">
                    <div class="file-upload">
                        <button class="file-upload-btn">
                            <i class="fas fa-file-upload"></i>
                            上传Excel数据
                        </button>
                        <input type="file" id="file-input" accept=".xlsx, .xls">
                    </div>

                    <div class="file-upload">
                        <button class="file-upload-btn update">
                            <i class="fas fa-sync"></i> 更新本次考试数据
                        </button>

                        <button class="file-upload-btn reset">
                            <i class="fas fa-trash"></i> 重置数据
                        </button>

                        <button class="file-upload-btn update-data" id="update-exam-data-btn">
                            <i class="fas fa-cloud-download-alt"></i> 更新所有数据
                        </button>

                        <button class="file-upload-btn" id="clear-cache-btn">
                            <i class="fas fa-broom"></i> 清除缓存
                        </button>

                        <button class="file-upload-btn export">
                            <i class="fas fa-download"></i> 导出数据
                        </button>
                    </div>

                    <div class="class-filter">
                        <label for="class-select"><i class="fas fa-filter"></i> 班级筛选：</label>
                        <select id="class-select">
                            <option value="all">全部班级</option>
                            <!-- 班级选项将动态生成 -->
                        </select>
                    </div>
                </div>
            </div>

            <div class="exam-selector">
                <!-- 考试按钮将动态生成 -->
            </div>

            <div class="stats">
                <div class="stat-card">
                    <div class="stat-icon" style="background: #DBEAFE; color: #1D4ED8;">
                        <i class="fas fa-users"></i>
                    </div>
                    <div class="stat-content">
                        <div class="stat-value" id="total-students">0</div>
                        <div class="stat-label">学生总数</div>
                    </div>
                </div>

                <div class="stat-card">
                    <div class="stat-icon" style="background: #D1FAE5; color: #047857;">
                        <i class="fas fa-chalkboard-teacher"></i>
                    </div>
                    <div class="stat-content">
                        <div class="stat-value" id="class-count">0</div>
                        <div class="stat-label">班级数量</div>
                    </div>
                </div>

                <div class="stat-card">
                    <div class="stat-icon" style="background: #FEF3C7; color: #B45309;">
                        <i class="fas fa-chart-line"></i>
                    </div>
                    <div class="stat-content">
                        <div class="stat-value" id="avg-score">0</div>
                        <div class="stat-label">平均成绩</div>
                    </div>
                </div>

                <div class="stat-card">
                    <div class="stat-icon" style="background: #FCE7F3; color: #DB2777;">
                        <i class="fas fa-trophy"></i>
                    </div>
                    <div class="stat-content">
                        <div class="stat-value" id="top-score">0</div>
                        <div class="stat-label">最高分数</div>
                    </div>
                </div>
            </div>
        </header>

        <div class="table-container">
            <div class="table-header">
                <h2 class="table-title">
                    <i class="fas fa-table"></i>
                    <span id="current-exam-title">第1周考试</span> - 学生信息列表
                </h2>
                <div class="search-box">
                    <i class="fas fa-search"></i>
                    <input type="text" id="search-input" placeholder="搜索学生姓名、考号或座号">
                </div>
            </div>

            <div id="table-content">
                <div class="empty-state">
                    <i class="fas fa-file-excel"></i>
                    <h3>暂无学生数据</h3>
                    <p>请上传Excel文件以加载学生数据</p>
                </div>
            </div>

            <div class="file-requirements">
                <h4><i class="fas fa-info-circle"></i> Excel文件要求：</h4>
                <p>表格必须包含以下列：<strong>班级</strong>、<strong>姓名</strong>、<strong>考号</strong>、<strong>座号</strong>、<strong>成绩</strong>
                </p>
                <p>第一行应为表头，数据从第二行开始</p>
            </div>
        </div>

        <!-- 添加考试模态框 -->
        <div class="modal" id="add-exam-modal">
            <div class="modal-content">
                <div class="modal-header">
                    <h3 class="modal-title">添加新考试</h3>
                    <button class="close-modal">&times;</button>
                </div>

                <div class="form-group">
                    <label for="exam-name">考试名称</label>
                    <input type="text" id="exam-name" placeholder="例如：第九周考试">
                </div>

                <div class="form-group">
                    <label for="exam-url">数据URL（可选）</label>
                    <input type="text" id="exam-url" placeholder="https://example.com/data.xlsx">
                </div>

                <div class="modal-actions">
                    <button class="modal-btn secondary close-modal">取消</button>
                    <button class="modal-btn primary" id="save-exam-btn">保存</button>
                </div>
            </div>
        </div>

        <!-- 删除考试模态框 -->
        <div class="modal" id="delete-exam-modal">
            <div class="modal-content">
                <div class="modal-header">
                    <h3 class="modal-title">删除考试</h3>
                    <button class="close-modal">&times;</button>
                </div>

                <div class="form-group">
                    <p id="delete-exam-message">您确定要删除考试 "<span id="exam-to-delete-name"></span>" 吗？</p>
                    <p class="warning-text"><i class="fas fa-exclamation-triangle"></i> 此操作不可撤销，所有相关数据将被永久删除。</p>
                </div>

                <div class="modal-actions">
                    <button class="modal-btn secondary close-modal">取消</button>
                    <button class="modal-btn danger" id="confirm-delete-btn">确认删除</button>
                </div>
            </div>
        </div>

        <footer>
            <p>© 2025 学生成绩管理系统 | 支持多考试管理及排名功能</p>
        </footer>
    </div>

    <script>
        // 中文表头到英文字段的映射
        const columnMapping = {
            '班级': 'class',
            '姓名': 'name',
            '考号': 'id',
            '座号': 'seat',
            '成绩': 'score'
        };

        // DOM元素
        const fileInput = document.getElementById('file-input');
        const classSelect = document.getElementById('class-select');
        const searchInput = document.getElementById('search-input');
        const tableContent = document.getElementById('table-content');
        const totalStudents = document.getElementById('total-students');
        const classCount = document.getElementById('class-count');
        const avgScore = document.getElementById('avg-score');
        const topScore = document.getElementById('top-score');
        const updateBtn = document.querySelector('.update');
        const resetBtn = document.querySelector('.reset');
        const exportBtn = document.querySelector('.export');
        const clearCacheBtn = document.getElementById('clear-cache-btn');
        const updateExamDataBtn = document.getElementById('update-exam-data-btn');
        const addExamBtn = document.getElementById('add-exam-btn');
        const saveExamBtn = document.getElementById('save-exam-btn');
        const addExamModal = document.getElementById('add-exam-modal');
        const deleteExamModal = document.getElementById('delete-exam-modal');
        const closeModalBtns = document.querySelectorAll('.close-modal');
        const currentExamTitle = document.getElementById('current-exam-title');
        const examToDeleteName = document.getElementById('exam-to-delete-name');
        const confirmDeleteBtn = document.getElementById('confirm-delete-btn');
        const deleteExamMessage = document.getElementById('delete-exam-message');
        const loadingOverlay = document.getElementById('loading-overlay');

        // 当前展示的数据和考试
        let currentData = [];
        let currentFilteredData = [];
        // 默认展示考试的ID
        let currentExamId = 'week1';
        let exams = {};
        let examToDeleteId = null;

        // ===================== 初始化函数 =====================
        // 初始化考试数据
        // 定义更新间隔（3小时）
        const UPDATE_INTERVAL = 6 * 60 * 60 * 1000; // 毫秒

        async function initExams() {
            loadingOverlay.style.display = 'flex';
            const now = Date.now();

            try {
                const savedExams = localStorage.getItem('exams');
                // 打印数据，准备调试图表
                // console.log(savedExams);
                let localExams = savedExams ? JSON.parse(savedExams) : {};

                // 检查上次更新时间
                const lastUpdate = localStorage.getItem('lastUpdate');
                const shouldUpdate = !lastUpdate || (now - parseInt(lastUpdate)) > UPDATE_INTERVAL;

                let remoteExams = {};
                if (shouldUpdate) {
                    // 只有超过3小时才从网络获取最新配置
                    remoteExams = await fetchExamConfig();
                    localStorage.setItem('lastUpdate', now.toString());
                } else {
                    console.log('3小时内已更新过，跳过网络请求');
                }

                // 合并配置（无论是否更新都执行，确保使用最新本地数据）
                exams = mergeExamConfigs(localExams, remoteExams);

                // 保存合并后的考试配置
                saveExams();

                // 更新考试选择器
                updateExamSelector();

                // 加载当前考试数据
                loadCurrentExam();

                // 仅在确实有更新时显示提示
                if (shouldUpdate && Object.keys(remoteExams).length > 0) {
                    const updatedExams = Object.values(remoteExams).filter(e => e.updated);
                    if (updatedExams.length > 0) {
                        const names = updatedExams.map(e => e.name).join(', ');
                        alert(`已更新以下考试数据源: ${names}`);
                    }
                }
            } catch (error) {
                console.error('初始化考试数据失败:', error);
                alert('加载考试配置失败，使用本地缓存数据');

                // 尝试使用本地缓存
                const savedExams = localStorage.getItem('exams');
                exams = savedExams ? JSON.parse(savedExams) : {};
                updateExamSelector();
                loadCurrentExam();
            } finally {
                setTimeout(() => {
                    loadingOverlay.style.opacity = '0';
                    setTimeout(() => {
                        loadingOverlay.style.display = 'none';
                        loadingOverlay.style.opacity = '1';
                    }, 500);
                }, 500);
            }
        }

        async function fetchExamConfig() {
            try {
                const response = await fetch('https://zc-oss2.oss-cn-hongkong.aliyuncs.com/lhsz/ttoolsData.json', {
                    cache: 'no-store' // 确保获取最新数据，跳过缓存
                });

                if (!response.ok) {
                    throw new Error(`网络请求失败: ${response.status} ${response.statusText}`);
                }

                const configData = await response.json();
                console.log('成功获取考试配置:', configData);
                return configData; // 直接返回JSON解析后的数据

            } catch (error) {
                console.error('获取考试配置时出错:', error);
                // 可选：返回模拟数据作为降级方案
                return {};
            }
        }


        // 合并考试配置
        function mergeExamConfigs(localExams, remoteExams) {
            const merged = { ...localExams };

            // 更新同名考试
            for (const [id, remoteExam] of Object.entries(remoteExams)) {
                // 检查是否存在同名考试
                const existingExam = Object.values(merged).find(e => e.name === remoteExam.name);

                if (existingExam) {
                    // 更新现有考试
                    existingExam.url = remoteExam.url;
                    existingExam.des = remoteExam.des;
                    existingExam.updated = true;
                } else {
                    // 添加新考试
                    merged[id] = { ...remoteExam, updated: true };
                }
            }

            return merged;
        }

        // 保存考试配置
        function saveExams() {
            localStorage.setItem('exams', JSON.stringify(exams));
        }

        // 清除缓存
        clearCacheBtn.addEventListener('click', function () {
            if (confirm('确定要清除所有缓存数据吗？此操作将删除所有考试及其数据，且不可恢复！')) {
                // 清除本地存储中的所有考试数据
                localStorage.removeItem('exams');

                // 重置当前状态
                exams = {};
                currentData = [];
                currentFilteredData = [];

                // 重新初始化默认考试
                // initExams();

                // 更新UI
                // updateStats([]);
                // updateClassSelect([]);
                // renderTable([]);

                alert('所有缓存数据已清除，系统已重置！');
            }
        });

        // 更新考试选择器
        function updateExamSelector() {
            const examSelector = document.querySelector('.exam-selector');
            examSelector.innerHTML = '';

            Object.values(exams).forEach(exam => {
                const isActive = exam.id === currentExamId;
                const btn = document.createElement('button');
                btn.className = `exam-btn ${isActive ? 'active' : ''}`;
                btn.dataset.examId = exam.id;
                btn.innerHTML = `
                    <i class="fas fa-calendar-week"></i>
                    <span>${exam.name}</span>
                    <div class="status-indicator ${exam.updated ? 'loading' : exam.data ? '' : 'outdated'}"></div>
                    <div class="delete-exam-btn" title="删除考试" data-exam-id="${exam.id}">
                        <i class="fas fa-times"></i>
                    </div>
                `;
                btn.addEventListener('click', () => switchExam(exam.id));
                examSelector.appendChild(btn);
            });

            // 添加"添加考试"按钮
            const addBtn = document.createElement('button');
            addBtn.className = 'exam-btn add';
            addBtn.id = 'add-exam-btn';
            addBtn.innerHTML = `
                <i class="fas fa-plus"></i>
                <span>添加考试</span>
            `;
            addBtn.addEventListener('click', () => {
                document.getElementById('exam-name').value = '';
                document.getElementById('exam-url').value = '';
                addExamModal.style.display = 'flex';
            });
            examSelector.appendChild(addBtn);

            // 为所有删除按钮添加事件监听
            document.querySelectorAll('.delete-exam-btn').forEach(btn => {
                btn.addEventListener('click', function (e) {
                    e.stopPropagation(); // 阻止冒泡，避免触发考试切换
                    const examId = this.dataset.examId;
                    const examName = exams[examId].name;
                    examToDeleteId = examId;
                    examToDeleteName.textContent = examName;
                    deleteExamMessage.innerHTML = `您确定要删除考试 "<span id="exam-to-delete-name">${examName}</span>" 吗？`;
                    deleteExamModal.style.display = 'flex';
                });
            });
        }

        // 切换到指定考试
        function switchExam(examId) {
            currentExamId = examId;
            currentExamTitle.textContent = exams[examId].name;
            updateExamSelector();
            loadCurrentExam();
        }

        // 加载当前考试数据
        function loadCurrentExam() {
            const exam = exams[currentExamId];

            if (exam.data) {
                // 已有数据，直接显示
                currentData = exam.data;
                currentFilteredData = [...currentData];
                updateStats(currentFilteredData);
                updateClassSelect(currentData);
                renderTable(currentFilteredData);
            } else if (exam.url) {
                // 有URL但无数据，尝试加载
                showInitialEmptyState('正在加载考试数据...');
                fetchExcelData(exam.url).then(networkData => {
                    if (networkData) {
                        const processedData = processExcelData(networkData);
                        exam.data = processedData;
                        saveExams();
                        currentData = processedData;
                        currentFilteredData = [...currentData];
                        updateStats(currentFilteredData);
                        updateClassSelect(currentData);
                        renderTable(currentFilteredData);
                    } else {
                        showInitialEmptyState('网络请求失败，请手动上传文件');
                    }
                }).catch(error => {
                    console.error('加载考试数据出错:', error);
                    showInitialEmptyState('加载数据失败，请手动上传');
                });
            } else {
                // 无数据也无URL
                showInitialEmptyState('请上传Excel文件以加载数据');
                currentData = [];
                currentFilteredData = [];
                updateStats([]);
                updateClassSelect([]);
                renderTable([]);
            }
        }

        // ===================== 核心功能函数 =====================
        // 计算排名（按照要求：分数相同排名相同，下一分数排名=上一排名+相同分数人数）
        function calculateRanks(data) {
            if (data.length === 0) return data;

            // 计算年级排名
            const gradeRanked = [...data].sort((a, b) => b.score - a.score);
            let rank = 1;
            let prevScore = gradeRanked[0].score;
            let sameScoreCount = 1;

            for (let i = 0; i < gradeRanked.length; i++) {
                const student = gradeRanked[i];

                if (i === 0) {
                    student.gradeRank = rank;
                    continue;
                }

                if (student.score === prevScore) {
                    student.gradeRank = rank;
                    sameScoreCount++;
                } else {
                    rank += sameScoreCount;
                    student.gradeRank = rank;
                    sameScoreCount = 1;
                    prevScore = student.score;
                }
            }

            // 计算班级排名
            const classGroups = {};
            data.forEach(student => {
                if (!classGroups[student.class]) {
                    classGroups[student.class] = [];
                }
                classGroups[student.class].push(student);
            });

            for (const cls in classGroups) {
                const classData = [...classGroups[cls]].sort((a, b) => b.score - a.score);
                let classRank = 1;
                let prevClassScore = classData[0].score;
                let sameClassScoreCount = 1;

                for (let i = 0; i < classData.length; i++) {
                    const student = classData[i];

                    if (i === 0) {
                        student.classRank = classRank;
                        continue;
                    }

                    if (student.score === prevClassScore) {
                        student.classRank = classRank;
                        sameClassScoreCount++;
                    } else {
                        classRank += sameClassScoreCount;
                        student.classRank = classRank;
                        sameClassScoreCount = 1;
                        prevClassScore = student.score;
                    }
                }
            }

            return gradeRanked;
        }

        // 从网络获取Excel数据
        async function fetchExcelData(url) {
            if (!url) return null;

            try {
                const response = await fetch(url, {
                    mode: 'cors',
                    headers: {
                        'Origin': location.origin
                    }
                });

                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }

                const arrayBuffer = await response.arrayBuffer();
                const data = new Uint8Array(arrayBuffer);
                const workbook = XLSX.read(data, { type: 'array' });
                const worksheet = workbook.Sheets[workbook.SheetNames[0]];
                return XLSX.utils.sheet_to_json(worksheet);
            } catch (error) {
                console.error('网络请求详细错误:', error);
                alert(`网络请求失败: ${error.message}\n请检查网络连接或手动上传文件`);
                return null;
            }
        }

        // 处理Excel数据
        function processExcelData(data) {
            const processedData = data.map(row => {
                const newRow = {};
                for (const [chineseHeader, englishField] of Object.entries(columnMapping)) {
                    if (row[chineseHeader] !== undefined) {
                        newRow[englishField] = row[chineseHeader];
                    }
                }
                // 确保成绩是数字
                if (newRow.score) {
                    newRow.score = parseFloat(newRow.score);
                }
                return newRow;
            }).filter(row => !isNaN(row.score));

            // 计算排名
            return calculateRanks(processedData);
        }

        // ===================== UI更新函数 =====================
        // 显示初始空状态
        function showInitialEmptyState(message = '正在加载数据...') {
            tableContent.innerHTML = `
                <div class="empty-state">
                    <i class="fas fa-spinner fa-spin"></i>
                    <h3>${message}</h3>
                </div>
            `;
        }

        // 更新统计信息
        function updateStats(data) {
            totalStudents.textContent = data.length;

            const classes = new Set(data.map(student => student.class));
            classCount.textContent = classes.size;

            if (data.length > 0) {
                const scores = data.map(s => s.score).filter(s => !isNaN(s));
                if (scores.length > 0) {
                    const totalScore = scores.reduce((sum, score) => sum + score, 0);
                    const average = totalScore / scores.length;
                    const maxScore = Math.max(...scores);

                    avgScore.textContent = average.toFixed(1);
                    topScore.textContent = maxScore;
                    return;
                }
            }

            avgScore.textContent = '0.0';
            topScore.textContent = '0';
        }

        // 更新班级筛选下拉菜单
        function updateClassSelect(data) {
            while (classSelect.options.length > 1) {
                classSelect.remove(1);
            }

            const classes = [...new Set(data.map(student => student.class))];
            classes.sort((a, b) => {
                const numA = parseInt(a);
                const numB = parseInt(b);
                return !isNaN(numA) && !isNaN(numB) ? numA - numB : a.toString().localeCompare(b.toString());
            });

            classes.forEach(cls => {
                const option = document.createElement('option');
                option.value = cls;
                option.textContent = `班级 ${cls}`;
                classSelect.appendChild(option);
            });
        }

        // 渲染表格
        function renderTable(data) {
            if (data.length === 0) {
                tableContent.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-user-slash"></i>
                        <h3>没有符合条件的学生</h3>
                        <p>请尝试更改筛选条件或搜索关键词</p>
                    </div>
                `;
                return;
            }

            let tableHTML = `
                <table>
                    <thead>
                        <tr>
                            <th>考号</th>
                            <th>姓名</th>
                            <th>班级</th>
                            <th>座号</th>
                            <th>成绩</th>
                            <th>班级排名</th>
                            <th>年级排名</th>
                            <th>操作</th>
                        </tr>
                    </thead>
                    <tbody>
            `;

            data.forEach(student => {
                const score = student.score || 0;
                let scoreClass = 'score-medium';
                if (score >= 90) scoreClass = 'score-high';
                else if (score < 60) scoreClass = 'score-low';

                // 为前三名添加特殊样式
                let classRankClass = '';
                let classRankDisplay = student.classRank;

                if (student.classRank === 1) {
                    classRankClass = 'rank-1';
                    classRankDisplay = '<i class="fas fa-crown"></i> 1';
                } else if (student.classRank === 2) {
                    classRankClass = 'rank-2';
                } else if (student.classRank === 3) {
                    classRankClass = 'rank-3';
                }

                tableHTML += `
                    <tr>
                        <td class="student-id">${student.id || '未提供'}</td>
                        <td>${student.name || '未提供'}</td>
                        <td><span class="class-badge">${student.class || '未提供'}</span></td>
                        <td>${student.seat || '未提供'}</td>
                        <td><span class="${scoreClass}">${score}</span></td>
                        <td class="${classRankClass}">${classRankDisplay}</td>
                        <td>${student.gradeRank}</td>
                        <td>
                            <div class="actions">
                                <div class="action-btn" title="查看详情" onclick="viewStudent('${student.id}')">
                                    <i class="fas fa-eye"></i>
                                </div>
                                <div class="action-btn" title="编辑" onclick="editStudent('${student.id}')">
                                    <i class="fas fa-edit"></i>
                                </div>
                            </div>
                        </td>
                    </tr>
                `;
            });

            tableHTML += `
                    </tbody>
                </table>
            `;

            tableContent.innerHTML = tableHTML;
        }

        // ===================== 筛选和搜索功能 =====================
        // 筛选数据
        function filterData() {
            const selectedClass = classSelect.value;
            const searchTerm = searchInput.value.toLowerCase();

            currentFilteredData = [...currentData];

            if (selectedClass !== 'all') {
                currentFilteredData = currentFilteredData.filter(student =>
                    student.class && student.class.toString() === selectedClass.toString()
                );
            }

            if (searchTerm) {
                currentFilteredData = currentFilteredData.filter(student => {
                    const name = student.name ? student.name.toString().toLowerCase() : '';
                    const id = student.id ? student.id.toString().toLowerCase() : '';
                    const seat = student.seat ? student.seat.toString().toLowerCase() : '';
                    return name.includes(searchTerm) || id.includes(searchTerm) || seat.includes(searchTerm);
                });
            }

            updateStats(currentFilteredData);
            renderTable(currentFilteredData);
        }

        // 班级筛选
        classSelect.addEventListener('change', function () {
            filterData();
        });

        // 搜索功能
        searchInput.addEventListener('input', function () {
            filterData();
        });

        // ===================== 学生操作函数 =====================
        // 查看学生详情
        function viewStudent(studentId) {
            const student = currentData.find(s => s.id === studentId);
            if (student) {
                alert(`学生详情：
姓名：${student.name}
考号：${student.id}
班级：${student.class}
座号：${student.seat}
成绩：${student.score || '未提供'}
班级排名：${student.classRank}
年级排名：${student.gradeRank}`);
            }
        }

        // 编辑学生信息
        function editStudent(studentId) {
            const student = currentData.find(s => s.id === studentId);
            if (student) {
                const newScore = prompt(`编辑 ${student.name} 的成绩：`, student.score);
                if (newScore !== null) {
                    const parsedScore = parseFloat(newScore);
                    if (!isNaN(parsedScore)) {
                        student.score = parsedScore;
                        // 更新考试数据并重新计算排名
                        exams[currentExamId].data = calculateRanks(currentData);
                        currentData = exams[currentExamId].data;
                        saveExams();
                        filterData();
                        alert("成绩已更新！排名已重新计算");
                    } else {
                        alert("请输入有效的数字成绩");
                    }
                }
            }
        }

        // ===================== 文件上传处理 =====================
        // 文件上传处理
        fileInput.addEventListener('change', function (e) {
            const file = e.target.files[0];
            if (!file) return;

            showInitialEmptyState('正在处理文件...');

            const reader = new FileReader();
            reader.onload = function (e) {
                try {
                    const data = new Uint8Array(e.target.result);
                    const workbook = XLSX.read(data, { type: 'array' });

                    if (workbook.SheetNames.length === 0) {
                        throw new Error('Excel文件不包含有效工作表');
                    }

                    const worksheet = workbook.Sheets[workbook.SheetNames[0]];
                    const jsonData = XLSX.utils.sheet_to_json(worksheet);

                    if (jsonData.length === 0) {
                        throw new Error('Excel文件不包含有效数据');
                    }

                    const processedData = processExcelData(jsonData);

                    // 保存到当前考试
                    exams[currentExamId].data = processedData;
                    saveExams();
                    currentData = processedData;
                    currentFilteredData = [...currentData];

                    // 更新UI
                    updateStats(currentFilteredData);
                    updateClassSelect(currentData);
                    renderTable(currentFilteredData);
                } catch (error) {
                    console.error('文件处理错误:', error);
                    alert(`文件处理失败: ${error.message}\n请确保文件格式正确`);
                    showInitialEmptyState();
                }
            };
            reader.onerror = function (e) {
                console.error('文件读取错误:', e);
                alert('文件读取失败，请重试');
                showInitialEmptyState();
            };
            reader.readAsArrayBuffer(file);
        });

        // 模拟文件上传功能
        document.querySelector('.file-upload-btn').addEventListener('click', function () {
            if (!fileInput.files.length) {
                fileInput.click();
            }
        });

        // ===================== 导出功能 =====================
        // 创建导出选项
        const exportOptions = document.createElement('div');
        exportOptions.className = 'export-options';
        exportOptions.innerHTML = `
            <div class="export-option" data-type="current">
                <i class="fas fa-table"></i> 导出当前视图数据
            </div>
            <div class="export-option" data-type="all">
                <i class="fas fa-database"></i> 导出全部数据
            </div>
        `;
        document.querySelector('.header-controls').appendChild(exportOptions);

        // 显示/隐藏导出选项
        exportBtn.addEventListener('click', function (e) {
            exportOptions.classList.toggle('active');
            e.stopPropagation();
        });

        // 点击外部关闭导出选项
        document.addEventListener('click', function (e) {
            if (!exportOptions.contains(e.target)) {
                exportOptions.classList.remove('active');
            }
        });

        // 处理导出选项点击
        exportOptions.addEventListener('click', function (e) {
            const option = e.target.closest('.export-option');
            if (option) {
                const exportType = option.dataset.type;
                exportOptions.classList.remove('active');

                if (exportType === 'current') {
                    exportCurrentView();
                } else if (exportType === 'all') {
                    exportAllData();
                }
            }
        });

        // 导出当前视图数据
        function exportCurrentView() {
            if (currentFilteredData.length === 0) {
                alert('没有可导出的数据');
                return;
            }

            const workbook = XLSX.utils.book_new();
            const exportData = currentFilteredData.map(student => ({
                班级: student.class,
                姓名: student.name,
                考号: student.id,
                座号: student.seat,
                成绩: student.score,
                班级排名: student.classRank,
                年级排名: student.gradeRank
            }));

            const worksheet = XLSX.utils.json_to_sheet(exportData);
            XLSX.utils.book_append_sheet(workbook, worksheet, '学生数据');

            const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
            const blob = new Blob([excelBuffer], { type: 'application/octet-stream' });
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `${exams[currentExamId].name}_筛选数据.xlsx`;
            a.click();
            window.URL.revokeObjectURL(url);
        }

        // 导出全部数据
        function exportAllData() {
            if (currentData.length === 0) {
                alert('没有可导出的数据');
                return;
            }

            const workbook = XLSX.utils.book_new();
            const exportData = currentData.map(student => ({
                班级: student.class,
                姓名: student.name,
                考号: student.id,
                座号: student.seat,
                成绩: student.score,
                班级排名: student.classRank,
                年级排名: student.gradeRank
            }));

            const worksheet = XLSX.utils.json_to_sheet(exportData);
            XLSX.utils.book_append_sheet(workbook, worksheet, '学生数据');

            const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
            const blob = new Blob([excelBuffer], { type: 'application/octet-stream' });
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `${exams[currentExamId].name}_全部数据.xlsx`;
            a.click();
            window.URL.revokeObjectURL(url);
        }

        // ===================== 删除考试功能 =====================
        // 确认删除考试
        confirmDeleteBtn.addEventListener('click', function () {
            if (!examToDeleteId) return;

            const examName = exams[examToDeleteId].name;

            // 检查是否是最后一个考试
            if (Object.keys(exams).length <= 1) {
                alert('不能删除最后一个考试！');
                deleteExamModal.style.display = 'none';
                return;
            }

            // 删除考试
            delete exams[examToDeleteId];
            saveExams();

            // 如果删除的是当前考试，切换到另一个考试
            if (currentExamId === examToDeleteId) {
                // 获取第一个可用的考试ID
                const firstExamId = Object.keys(exams)[0];
                switchExam(firstExamId);
                alert(`考试 "${examName}" 已删除，已切换到 "${exams[firstExamId].name}"`);
            } else {
                alert(`考试 "${examName}" 已删除`);
            }

            // 关闭模态框
            deleteExamModal.style.display = 'none';
            examToDeleteId = null;
        });

        // ===================== 其他功能 =====================
        // 更新数据按钮
        updateBtn.addEventListener('click', function () {
            const exam = exams[currentExamId];
            if (!exam.url) {
                alert('当前考试没有配置数据URL，请手动上传数据');
                return;
            }

            showInitialEmptyState('正在更新数据...');
            fetchExcelData(exam.url).then(networkData => {
                if (networkData) {
                    const processedData = processExcelData(networkData);
                    exam.data = processedData;
                    saveExams();
                    currentData = processedData;
                    currentFilteredData = [...currentData];
                    updateStats(currentFilteredData);
                    updateClassSelect(currentData);
                    renderTable(currentFilteredData);
                    alert('数据更新成功！排名已计算');
                } else {
                    alert('网络请求失败，请检查URL或手动上传');
                }
            });
        });

        // 手动更新考试数据
        updateExamDataBtn.addEventListener('click', async function () {
            loadingOverlay.style.display = 'flex';

            try {
                // 从网络获取最新考试配置
                const remoteExams = await fetchExamConfig();

                // 合并本地和远程考试配置
                exams = mergeExamConfigs(exams, remoteExams);

                // 保存合并后的考试配置
                saveExams();

                // 更新考试选择器
                updateExamSelector();

                // 加载当前考试数据
                loadCurrentExam();

                // 检查是否有更新
                const updatedExams = Object.values(exams).filter(e => e.updated);
                if (updatedExams.length > 0) {
                    const names = updatedExams.map(e => e.name).join(', ');
                    alert(`已更新以下考试数据源: ${names}`);
                } else {
                    alert('所有考试数据已是最新版本');
                }
            } catch (error) {
                console.error('更新考试数据失败:', error);
                alert('更新考试数据失败，请检查网络连接');
            } finally {
                setTimeout(() => {
                    loadingOverlay.style.opacity = '0';
                    setTimeout(() => {
                        loadingOverlay.style.display = 'none';
                        loadingOverlay.style.opacity = '1';
                    }, 500);
                }, 500);
            }
        });

        // 重置数据按钮
        resetBtn.addEventListener('click', function () {
            if (confirm('确定要重置当前考试的所有数据吗？')) {
                exams[currentExamId].data = null;
                saveExams();
                currentData = [];
                currentFilteredData = [];
                updateStats([]);
                updateClassSelect([]);
                renderTable([]);
                showInitialEmptyState('数据已重置');
            }
        });

        // 添加考试功能
        saveExamBtn.addEventListener('click', function () {
            const examName = document.getElementById('exam-name').value.trim();
            const examUrl = document.getElementById('exam-url').value.trim();

            if (!examName) {
                alert('请输入考试名称');
                return;
            }

            // 生成唯一的考试ID
            const examId = 'exam_' + Date.now();

            // 创建新考试
            exams[examId] = {
                id: examId,
                name: examName,
                url: examUrl,
                data: null
            };

            saveExams();
            addExamModal.style.display = 'none';

            // 切换到新添加的考试
            switchExam(examId);
        });

        // 关闭模态框
        closeModalBtns.forEach(btn => {
            btn.addEventListener('click', () => {
                addExamModal.style.display = 'none';
                deleteExamModal.style.display = 'none';
            });
        });

        // 点击模态框外部关闭
        window.addEventListener('click', (e) => {
            if (e.target === addExamModal) {
                addExamModal.style.display = 'none';
            }
            if (e.target === deleteExamModal) {
                deleteExamModal.style.display = 'none';
            }
        });

        // ===================== 初始化页面 =====================
        // 初始化页面
        document.addEventListener('DOMContentLoaded', function () {
            initExams();
        });
    </script>
</body>

</html>